package br.com.linkin.mi.soap;

import br.com.linkin.mi.contants.Constant;
import br.com.linkin.mi.utils.Properties;
import java.io.ByteArrayInputStream;
import java.net.URL;
import java.security.Security;
import javax.xml.soap.*;
import javax.xml.transform.stream.StreamSource;
import org.w3c.dom.Document;

/**
 *
 * @author daniel.mendonca
 */
public class Soap {
    
    private static Soap instance = new Soap();
    
    /**
     * Soap instance
     * @return 
     */
    public static Soap instance() {
        return instance;
    }
    
    /**
     * create SOAP Message
     *
     * @param headerDoc
     * @param bodyDoc
     * @param soapAction
     * @return
     * @throws Exception
     */
    public static SOAPMessage create(Document headerDoc, Document bodyDoc, String soapAction) throws Exception {
        return Soap.instance().createSOAPMessage(headerDoc, bodyDoc, soapAction);
    }

    /**
     * send Message
     *
     * @param url
     * @param message
     * @return
     * @throws Exception
     */
    public static SOAPMessage send(String url, SOAPMessage message) throws Exception {
        return Soap.instance().sendMessage(url, message);
    }
    
    /**
     * to Message
     *
     * @param soapText
     * @return
     */
    public static SOAPMessage toMessage(String soapText) {
        SOAPMessage message = null;
        try {
            // Create SoapMessage
            MessageFactory msgFactory = MessageFactory.newInstance(SOAPConstants.SOAP_1_2_PROTOCOL);
            message = msgFactory.createMessage();
            SOAPPart soapPart = message.getSOAPPart();

            // Load the SOAP text into a stream source
            byte[] buffer = soapText.getBytes();
            ByteArrayInputStream stream = new ByteArrayInputStream(buffer);
            StreamSource source = new StreamSource(stream);

            soapPart.setContent(source);

        } catch (SOAPException e) {
            throw new RuntimeException(e);
        }
        return message;
    }
    
    /**
     * configurar Certificado
     */
    public static void configurarCertificado(){
        System.setProperty("java.protocol.handler.pkgs", "com.sun.net.ssl.internal.www.protocol");        
        Security.addProvider(new com.sun.net.ssl.internal.ssl.Provider());        
        System.setProperty("javax.net.ssl.keyStoreType", "PKCS12");
        System.clearProperty("javax.net.ssl.keyStore");
        System.clearProperty("javax.net.ssl.keyStorePassword");
        System.clearProperty("javax.net.ssl.trustStore");        
        System.setProperty("javax.net.ssl.keyStore", Properties.config(Constant.CERTIFICADO));
        System.setProperty("javax.net.ssl.keyStorePassword", Properties.config(Constant.KEY_STORE_PASS));
        System.setProperty("javax.net.ssl.trustStoreType", "JKS");
        System.setProperty("javax.net.ssl.trustStore", Properties.config(Constant.CACERTS));
    }
    
    /**
     * create SOAP Message
     *
     * @param headerDoc
     * @param bodyDoc
     * @param soapAction
     * @return
     * @throws Exception
     */
    private SOAPMessage createSOAPMessage(Document headerDoc, Document bodyDoc, String soapAction) throws Exception {
        MessageFactory factory = MessageFactory.newInstance(SOAPConstants.SOAP_1_2_PROTOCOL);
        SOAPMessage message = factory.createMessage();
        message.getMimeHeaders().addHeader("SOAPAction", soapAction);
        message.setProperty(SOAPMessage.WRITE_XML_DECLARATION, "true");
        SOAPPart soapPart = message.getSOAPPart();
        SOAPEnvelope envelope = soapPart.getEnvelope();
        SOAPHeader header = envelope.getHeader();
        Document doc = header.getOwnerDocument();
        if (headerDoc != null) {
            org.w3c.dom.Node node = doc.importNode(headerDoc.getDocumentElement(), true);
            header.appendChild(node);
        }

        SOAPBody body = envelope.getBody();
        body.addDocument(bodyDoc);
        
        return message;
    }

    /**
     * send Message
     *
     * @param url
     * @param message
     * @return
     * @throws Exception
     */
    private SOAPMessage sendMessage(String url, SOAPMessage message) throws Exception {
        SOAPConnectionFactory soapConnectionFactory = SOAPConnectionFactory.newInstance();
        SOAPConnection connection = soapConnectionFactory.createConnection();
        System.out.println("");
        message.writeTo(System.out);
        SOAPMessage response = connection.call(message, new URL(url));
        System.out.println("");
        response.writeTo(System.out);
        connection.close();
        return response;
    } 
    
}